package com.ys.service.sys.impl;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ys.config.MyConfig;
import com.ys.service.sys.UploadService;
import com.ys.util.DateUtil;
import com.ys.util.dhecp.FileUploadUtils;
import com.ys.util.upload.UploadUtilYs;
import com.ys.vo.R;

import cn.hutool.core.codec.Base64;

@Service("uploadService")
public class UploadServiceImpl implements UploadService {

//	private static final Logger logger = Logger.getLogger(UploadServiceImpl.class);

	@Override
	public R uploadfileForEditor(HttpServletRequest request, HttpServletResponse response, MultipartFile file, String moduleFile) throws IOException {

		if(!ServletFileUpload.isMultipartContent(request)){
			return R.error("请选择文件");
		}
		
		String toRelativePath = UploadUtilYs.getToRelativePath(moduleFile);
		String toRealPath = UploadUtilYs.getToRealPath(toRelativePath);

		try {
			InputStream fileInputStream = file.getInputStream();
			
			// 文件初始名
			String oriFilename = file.getOriginalFilename();
			
			// .号所在位置
			int lastIndex = oriFilename.lastIndexOf(".");
			
			// 扩展名
			String orgFileExt = oriFilename.substring(lastIndex + 1).toLowerCase();
			
			// 拼接文件名
			String toFilename = UploadUtilYs.getToFileName(orgFileExt);
			
			// 将文件保存到本地
			FileOutputStream fs = new FileOutputStream(toRealPath + "/" + toFilename);
			byte[] buffer = new byte[1024 * 1024];
			int byteread = 0;
			while ((byteread = fileInputStream.read(buffer)) != -1) {
				fs.write(buffer, 0, byteread);
				fs.flush();
			}
			fs.close();
			fileInputStream.close();
			
			UploadDto dto = new UploadDto(MyConfig.getUrlFile() + toRelativePath + "/" + toFilename);
			return R.ok(dto);
		} catch (IOException e) {
			e.printStackTrace();
			return R.error("上传失败");
		}
		
	}

	@Override
	public R uploadfileForLayer(HttpServletResponse response, MultipartFile file, String moduleFile) throws IOException {

		String toRelativePath = UploadUtilYs.getToRelativePath(moduleFile);
		String toRealPath = UploadUtilYs.getToRealPath(toRelativePath);
		
		File dirFile = new File(toRealPath);
		if (!dirFile.exists()) {
			dirFile.mkdirs();
		}

		try {
			InputStream fileInputStream = file.getInputStream();
			
			// 文件初始名
			String oriFilename = file.getOriginalFilename();
			
			// .号所在位置
			int lastIndex = oriFilename.lastIndexOf(".");
			
			// 扩展名
			String orgFileExt = oriFilename.substring(lastIndex + 1).toLowerCase();
			
			// 拼接文件名
			String toFilename = UploadUtilYs.getToFileName(orgFileExt);
			
			// 将文件保存到本地
			FileOutputStream fs = new FileOutputStream(toRealPath + "/" + toFilename);
			byte[] buffer = new byte[1024 * 1024];
			int byteread = 0;
			while ((byteread = fileInputStream.read(buffer)) != -1) {
				fs.write(buffer, 0, byteread);
				fs.flush();
			}
			fs.close();
			fileInputStream.close();
			
			UploadDto dto = new UploadDto(MyConfig.getUrlFile() + toRelativePath + "/" + toFilename);
			return R.ok(dto);
		} catch (IOException e) {
			e.printStackTrace();
			return R.error("上传失败");
		}
	}

	@Override
	public R uploadBase64(String body) throws IOException {
		
		try{
			if(body == null || body.length() == 0){
				return R.error("上传失败，上传图片数据为空");
			}
			JSONObject bodyJO = JSON.parseObject(body);
			String data = bodyJO.getString("base64Data");
			String sourceFileName = bodyJO.getString("sourceFileName");
			if (sourceFileName == null || sourceFileName.length() == 0) {
				return R.error("文件名不能为空");
			}
			String moduleFile = bodyJO.containsKey("moduleFile") ? bodyJO.getString("moduleFile") : "nomodule";
			String orgFileExt = sourceFileName.substring(sourceFileName.lastIndexOf(".") + 1);
			
    		String toRelativePath = UploadUtilYs.getToRelativePath(moduleFile);
			String toFilename = UploadUtilYs.getToFileName(orgFileExt);
			String toRealPath = UploadUtilYs.getToRealPath(toRelativePath);
			
			File dirFile = new File(toRealPath);
			if (!dirFile.exists()) {
				dirFile.mkdirs();
			}
			
            File toFile = new File(toRealPath + "/" + toFilename);
            BufferedOutputStream bos = new BufferedOutputStream(Files.newOutputStream(toFile.toPath()));
            byte[] bytes = Base64.decode(data);
            bos.write(bytes);
            bos.close();
            
        	UploadDto dto = new UploadDto(MyConfig.getUrlFile() + toRelativePath + "/" + toFilename);
        	
        	return R.ok(dto);
        } catch (Exception e) {
        	e.printStackTrace();
        	return R.error("上传失败");
        }
	}

	@Override
	public R uploadByUrl(String urlOld, String moduleFile) throws IOException {
		
		if (urlOld == null || urlOld.length() == 0) {
			return R.error("链接不能为空");
		} else if (!urlOld.startsWith("http")) {
			return R.error("链接格式必须以http开头");
		}

		if (moduleFile == null || moduleFile.length() == 0) {
			moduleFile = "nomodule";
		}
		
		// 验证文件类型
		// .号所在位置
		int lastIndex = urlOld.lastIndexOf(".");
		if (lastIndex <= 0) {
			return R.error("未知的文件类型");
		}
		// 扩展名
		String orgFileExt = urlOld.substring(lastIndex + 1).toLowerCase();
		// 支持的文件后缀列表
		/*
		String imageExts = "gif,jpg,jpeg,png,bmp,xls,xlsx,txt";
		if (!imageExts.contains(orgFileExt)) {
			return R.error("不支持的文件类型，请联系技术");
		}

		 */
		
		// 新路径的文件名
        try {
        	URL url = new URL(urlOld);
            // 打开连接
            URLConnection con = url.openConnection();
            int status =  ((HttpURLConnection) con).getResponseCode();
            if(status != 200){
    			return R.error("文件不存在");
            }
            //设置请求超时为5s
            con.setConnectTimeout(5*1000);
            // 输入流
            InputStream is = con.getInputStream();
            // 1K的数据缓冲
            byte[] bs = new byte[1024];
            // 读取到的数据长度
            int len;
            // 输出的文件流
            String toRelativePath = UploadUtilYs.getToRelativePath(moduleFile);
			String toFilename = UploadUtilYs.getToFileName(orgFileExt);
			String toRealPath = UploadUtilYs.getToRealPath(toRelativePath);
			
			File dirFile = new File(toRealPath);
			if (!dirFile.exists()) {
				dirFile.mkdirs();
			}
            
            //保存路径和文件名
			String toFileDir = toRealPath + "/" + toFilename;
            OutputStream os = new FileOutputStream(toFileDir);
            // 开始读取
            while ((len = is.read(bs)) != -1) {
                //开始保存
                os.write(bs, 0, len);
            }
            // 完毕，关闭所有链接
            os.close();
            is.close();
            
            UploadDto dto = new UploadDto(MyConfig.getUrlFile() + toRelativePath + "/" + toFilename);
    		return R.ok(dto);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("服务器正在开小差，请联系技术");
        }
	}

	@Override
	public R uploadfileFor1_0(MultipartFile file, String moduleFile) throws IOException {
		
		Date nowDate = new Date();
		String nowMonth = DateUtil.getYYYY_MM(nowDate);
		String nowDay = DateUtil.getDD(nowDate);

		if (moduleFile == null || moduleFile.length() == 0) {
			moduleFile = "nomodule";
		}
		String toRelativePath = "/upload/" + moduleFile + "/" + nowMonth.replace("-", "") + "/" + nowDay;
		String toRealPath = UploadUtilYs.getToRealPath(toRelativePath);
		
		File dirFile = new File(toRealPath);
		if (!dirFile.exists()) {
			dirFile.mkdirs();
		}

		try {
			InputStream fileInputStream = file.getInputStream();
			
			// 文件初始名
			String oriFilename = file.getOriginalFilename();
			
			// .号所在位置
			int lastIndex = oriFilename.lastIndexOf(".");
			
			// 扩展名
			String orgFileExt = oriFilename.substring(lastIndex + 1).toLowerCase();
			
			// 拼接文件名
			String toFilename = UploadUtilYs.getToFileName(orgFileExt);
			
			// 将文件保存到本地
			FileOutputStream fs = new FileOutputStream(toRealPath + "/" + toFilename);
			byte[] buffer = new byte[1024 * 1024];
			int byteread = 0;
			while ((byteread = fileInputStream.read(buffer)) != -1) {
				fs.write(buffer, 0, byteread);
				fs.flush();
			}
			fs.close();
			fileInputStream.close();

	        Map<String, String> mapObj = FileUploadUtils.convertFileSize(file.getSize());
	        Long fileSizeLong = file.getSize();
	        String fileSize = mapObj.containsKey("fileSize") ? mapObj.get("fileSize") : "";
	        String fileSizeUnit = mapObj.containsKey("fileSizeUnit") ? mapObj.get("fileSizeUnit") : "";
	        String fileType = FileUploadUtils.getExtension(file);
	        String fileName = file.getOriginalFilename();
	        String filePath = MyConfig.getUrlFile() + toRelativePath + "/" + toFilename;
			Upload1_0Dto dto = new Upload1_0Dto(fileSize, fileType, fileName, fileSizeUnit, filePath, fileSizeLong);
			return R.ok(dto);
		} catch (IOException e) {
			e.printStackTrace();
			return R.error();
		}
	}
}
